package org.EasyDevelop.Builder;

import org.EasyDevelop.Bean.Constants;
import org.EasyDevelop.Bean.FieldInfo;
import org.EasyDevelop.Bean.TableInfo;
import org.EasyDevelop.Utils.PropertiesUtils;
import org.EasyDevelop.Utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class ControllerBuilder {
    private static Logger logger = LoggerFactory.getLogger(ControllerBuilder.class);
    public static void execute(TableInfo tableInfo) {
        File folder = new File(Constants.PATH_CONTROLLER);

        if(!folder.exists()) folder.mkdirs();

        File poFile = new File(folder, tableInfo.getBeanName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("controller")) + Constants.JAVA_SUFFIX);

        OutputStream os = null;
        OutputStreamWriter osw = null;
        BufferedWriter bw = null;
        try {
            os = new FileOutputStream(poFile);
            osw = new OutputStreamWriter(os, "UTF8");
            bw = new BufferedWriter(osw);

            //package
            bw.write("package " + Constants.PACKAGE_CONTROLLER + ";");
            bw.newLine();
            bw.newLine();


            //import
            bw.write("import " + Constants.PACKAGE_CONTROLLER + ".base.BaseController;");
            bw.newLine();

            bw.write("import org.springframework.web.bind.annotation.*;");
            bw.newLine();


            bw.write("import javax.annotation.Resource;\n");
            String serviceName = tableInfo.getBeanName() + StringUtils.upperCaseFirstLetter("Service");
            String controllerName = tableInfo.getBeanName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("controller"));

            //import com.ming.easyDevelop.service.UsersService;
            bw.write("import " + Constants.PACKAGE_SERVICE + "." + serviceName + ";\n");

            if(Boolean.valueOf(Constants.ENABLE_VALID)){
                //import ValidListBean
                bw.write("import " + Constants.PACKAGE_CONTROLLER_BASE + "." + "ValidListBean;");
                bw.newLine();
                //@Valid
                bw.write("import javax.validation.Valid;");
                bw.newLine();
            }

            //import Bean
            bw.write("import " + Constants.PACKAGE_PO + "." + tableInfo.getBeanName() + ";\n");

            //ResponseVo
            bw.write("import " + Constants.PACKAGE_ENTITY_VO_RESPONSE_VO + ".ResponseVo;\n");

            //QUERY
            String queryName = tableInfo.getBeanName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("queryParam"));
            bw.write("import " + Constants.PACKAGE_QUERY + "." + queryName + ";\n");
            bw.write("import java.util.List;\n");

            //class comment
            CommentBuilder.createClassComment(bw,tableInfo.getComment() + " Controller API");
            //class start
            bw.write("@RequestMapping(\"/api/" + StringUtils.lowerCaseFirstLetter(tableInfo.getTableName()) + "\")\n");
            bw.write("@RestController");
            bw.newLine();
            bw.write("public class " + controllerName + " extends BaseController {");
            bw.newLine();

            //@Resource
            bw.write("\t@Resource\n");
            bw.write("\tprivate " + serviceName + " " + StringUtils.lowerCaseFirstLetter(serviceName) + ";\n");

            //methods
            bw.newLine();
            //findDataList
            bw.write("\t@RequestMapping(\"/list\")\n");
            bw.write("\tpublic ResponseVo getDataList(" + queryName+ " query){\n");
            bw.write("\t\treturn getSuccessResponseVo(this." + StringUtils.lowerCaseFirstLetter(serviceName) + ".findListByParam(query));\n");
            bw.write("\t}\n");
        
            String valid1 = Boolean.valueOf(Constants.ENABLE_VALID)?"@Valid ":"";
            String valid2 = Boolean.valueOf(Constants.ENABLE_VALID)?"list.getData()":"list";
            String valid3 = Boolean.valueOf(Constants.ENABLE_VALID)?"ValidListBean<":"List<";

            //add
            bw.write("\t@PostMapping(\"/add\")\n");
            bw.write("\tpublic ResponseVo add(" + valid1 + "@RequestBody " + tableInfo.getBeanName()+ " bean){\n");
            bw.write("\t\tthis." + StringUtils.lowerCaseFirstLetter(serviceName) + ".add(bean);\n");
            bw.write("\t\treturn getSuccessResponseVo(null);\n");
            bw.write("\t}\n");
            bw.newLine();
            //addOrUpdate
            bw.write("\t@PostMapping(\"/addOrUpdate\")\n");
            bw.write("\tpublic ResponseVo addOrUpdate(" + valid1 + "@RequestBody " + tableInfo.getBeanName()+ " bean){\n");
            bw.write("\t\tthis." + StringUtils.lowerCaseFirstLetter(serviceName) + ".addOrUpdate(bean);\n");
            bw.write("\t\treturn getSuccessResponseVo(null);\n");
            bw.write("\t}\n");
            bw.newLine();
            //addBatch
            bw.write("\t@PostMapping(\"/addBatch\")\n");
            bw.write("\tpublic ResponseVo addBatch(@RequestBody " + valid3  + tableInfo.getBeanName()+ "> list){\n");
            bw.write("\t\tthis." + StringUtils.lowerCaseFirstLetter(serviceName) + ".addBatch(" + valid2 + ");\n");
            bw.write("\t\treturn getSuccessResponseVo(null);\n");
            bw.write("\t}\n");
            bw.newLine();
            //addOrUpdateBatch
            bw.write("\t@PostMapping(\"/addOrUpdateBatch\")\n");
            bw.write("\tpublic ResponseVo addOrUpdateBatch(@RequestBody " + valid3 + tableInfo.getBeanName() + "> list){\n");
            bw.write("\t\tthis." + StringUtils.lowerCaseFirstLetter(serviceName) + ".addOrUpdateBatch(" + valid2 + ");\n");
            bw.write("\t\treturn getSuccessResponseVo(null);\n");
            bw.write("\t}\n");
            bw.newLine();

            //methodById
            generatedIdMethods(bw,tableInfo,StringUtils.lowerCaseFirstLetter(serviceName),valid1);
            


            bw.write("}");
            bw.flush();

        } catch (Exception e) {
            logger.error("创建Controller失败,{}",e);
        } finally {
            if(bw!=null)
                try{
                    bw.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            if(osw!=null)
                try{
                    osw.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            if(os!=null)
                try{
                    os.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
        }
    }

    private static void generatedIdMethods(BufferedWriter bw, TableInfo tableInfo, String serviceName,String valid1) throws IOException {
        StringBuilder methodParams = new StringBuilder();
        StringBuilder methodParams2 = new StringBuilder();
        StringBuilder methodName = new StringBuilder();
        for (Map.Entry<String, List<FieldInfo>> entry : tableInfo.getKeyIndexMap().entrySet()) {
            List<FieldInfo> keyFieldList = entry.getValue();

            //叠加索引相关值
            Integer idx = 0;
            for (FieldInfo fieldInfo : keyFieldList) {
                methodName.append(StringUtils.upperCaseFirstLetter(fieldInfo.getPropertyName()));
                methodParams.append(
                        fieldInfo.getJavaType() + " " +
                                StringUtils.lowerCaseFirstLetter(fieldInfo.getPropertyName())
                );
                methodParams2.append(
                        StringUtils.lowerCaseFirstLetter(fieldInfo.getPropertyName())
                );
                if(idx++<keyFieldList.size()-1){
                    methodName.append("And");
                    methodParams.append(", ");
                    methodParams2.append(", ");
                }
            }

            //select
            CommentBuilder.createMethodComment(bw,"根据" + methodName + "查询");
            StringBuilder url = new StringBuilder();

            for (String s : methodParams2.toString().replace(" ", "").split(",")) {
                url.append(StringUtils.upperCaseFirstLetter(s));
                url.append("And");
            }
            url = new StringBuilder(StringUtils.lowerCaseFirstLetter(url.substring(0,url.lastIndexOf("And"))));


            bw.write("\t@GetMapping(\"/" + url
                    + "\")\n");
            bw.write("\tpublic ResponseVo getBy" + methodName.toString());
            bw.write("(");
            bw.write(methodParams.toString());
            bw.write("){");
            bw.newLine();

            bw.write("\t\treturn getSuccessResponseVo(this." + serviceName + ".getBy" + methodName.toString() + "(" + methodParams2 + "));\n");

            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            //update
            CommentBuilder.createMethodComment(bw,"根据" + methodName + "更新");
            bw.write("\t@PutMapping(\"/" + url + "\")\n");
            bw.write("\tpublic ResponseVo updateBy" + methodName.toString());
            bw.write("(" + valid1 + "");
            bw.write(tableInfo.getBeanName() + " bean, ");
            bw.write(methodParams.toString());
            bw.write("){");
            bw.newLine();
            bw.write("\t\tthis." + serviceName + ".updateBy" + methodName.toString() + "(bean," + methodParams2 + ");\n");
            bw.write("\t\treturn getSuccessResponseVo(null);\n");
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            //delete
            CommentBuilder.createMethodComment(bw,"根据" + methodName + "删除");

            bw.write("\t@DeleteMapping(\"/" + url + "\")\n");
            bw.write("\tpublic ResponseVo deleteBy" + methodName.toString());
            bw.write("(");
            bw.write(methodParams.toString());
            bw.write("){");
            bw.newLine();
            bw.write("\t\tthis." + serviceName + ".deleteBy" + methodName.toString() + "(" + methodParams2 + ");\n");
            bw.write("\t\treturn getSuccessResponseVo(null);\n");
            bw.write("\t}");
            bw.newLine();
            bw.newLine();


            methodName = new StringBuilder();
            methodParams = new StringBuilder();
            methodParams2 = new StringBuilder();
        }


    }
    
}
